package com.alibaba.cirtus.ots.application.adapter.ability.facade.service.retry;

import com.alibaba.cirtus.ots.application.adapter.ability.facade.service.sap.MnSapIf007ServiceImpl;
import com.alibaba.cirtus.ots.application.adapter.ability.facade.service.sap.MnSapIf008ServiceImpl;
import com.alibaba.cirtus.ots.application.adapter.ability.facade.service.sap.MnSapIf013ServiceImpl;
import com.alibaba.cirtus.ots.application.adapter.ability.facade.service.sap.MnSapIf015ServiceImpl;
import com.alibaba.cirtus.ots.application.adapter.ability.facade.service.sap.MnSapIf017ServiceImpl;
import com.alibaba.cirtus.ots.application.adapter.ability.facade.service.sap.MnSapIf018ServiceImpl;
import com.alibaba.cirtus.ots.application.adapter.ability.facade.serviceV2.sap.MnSapIf007V2ServiceImpl;
import com.alibaba.cirtus.ots.application.adapter.ability.facade.serviceV2.sap.MnSapIf008V2ServiceImpl;
import com.alibaba.cirtus.ots.application.adapter.ability.facade.serviceV2.sap.MnSapIf013V2ServiceImpl;
import com.alibaba.cirtus.ots.application.adapter.ability.facade.serviceV2.sap.MnSapIf015V2ServiceImpl;
import com.alibaba.cirtus.ots.application.adapter.ability.facade.serviceV2.sap.MnSapIf017V2ServiceImpl;
import com.alibaba.cirtus.ots.application.adapter.ability.facade.serviceV2.sap.MnSapIf018V2ServiceImpl;
import com.alibaba.cirtus.ots.application.adapter.ability.facade.serviceV2.sap.MnSapIf019V2ServiceImpl;
import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.fastjson.JSON;
import com.alibaba.lattice2.epoch.sdk.model.Result;
import com.epoch.app.otsapplicationadaptersdk.model.dto.MnSapIf019Request;
import com.epoch.app.otsapplicationadaptersdk.model.dto.SapRetryBatchRetryRequest;
import com.epoch.app.otsapplicationadaptersdk.model.dto.SapRetryBatchRetryResponse;
import com.epoch.app.otsapplicationadaptersdk.model.dto.SapRetryLoadListRequest;
import com.epoch.app.otsapplicationadaptersdk.model.dto.SapRetryRetryRequest;
import com.epoch.app.otsapplicationadaptersdk.model.dto.SapRetryRetryResponse;
import com.epoch.app.otsapplicationadaptersdk.model.dto.SapRetrySaveRequest;
import com.epoch.app.otsapplicationadaptersdk.model.dto.SapRetrySaveResponse;
import com.epoch.app.otsapplicationadaptersdk.model.enums.RetryStatus;
import com.epoch.app.otsapplicationadaptersdk.model.enums.SapApiCode;
import com.epoch.app.otsapplicationadaptersdk.sap.MnSapCommResponse;
import com.epoch.app.otsapplicationadaptersdk.sap.MnSapIf007Request;
import com.epoch.app.otsapplicationadaptersdk.sap.MnSapIf008Request;
import com.epoch.app.otsapplicationadaptersdk.sap.MnSapIf013Request;
import com.epoch.app.otsapplicationadaptersdk.sap.MnSapIf015Request;
import com.epoch.app.otsapplicationadaptersdk.sap.MnSapIf017Request;
import com.epoch.app.otsapplicationadaptersdk.sap.MnSapIf018Request;
import com.epoch.app.otsapplicationadaptersdk.sap.mnsapif007.service.MnSapIf007Service;
import com.epoch.app.otsapplicationadaptersdk.sap.mnsapif008.service.MnSapIf008Service;
import com.epoch.app.otsapplicationadaptersdk.sap.mnsapif013.service.MnSapIf013Service;
import com.epoch.app.otsapplicationadaptersdk.sap.mnsapif015.service.MnSapIf015Service;
import com.epoch.app.otsapplicationadaptersdk.sap.mnsapif017.service.MnSapIf017Service;
import com.epoch.app.otsapplicationadaptersdk.sap.mnsapif018.service.MnSapIf018Service;
import com.epoch.app.otsapplicationadaptersdk.sapretry.dto.LoadRequest;
import com.epoch.app.otsapplicationadaptersdk.sapretry.model.SapRetry;
import com.epoch.app.otsapplicationadaptersdk.sapretry.service.SapRetryService;
import com.epoch.app.otsapplicationadaptersdk.sapretrywrite.service.SapRetryWriteService;
import com.epoch.app.otsapplicationadaptersdk.sapv2.mnsapif007v2.service.MnSapIf007V2Service;
import com.epoch.app.otsapplicationadaptersdk.sapv2.mnsapif008v2.service.MnSapIf008V2Service;
import com.epoch.app.otsapplicationadaptersdk.sapv2.mnsapif013v2.service.MnSapIf013V2Service;
import com.epoch.app.otsapplicationadaptersdk.sapv2.mnsapif015v2.service.MnSapIf015V2Service;
import com.epoch.app.otsapplicationadaptersdk.sapv2.mnsapif017v2.service.MnSapIf017V2Service;
import com.epoch.app.otsapplicationadaptersdk.sapv2.mnsapif018v2.service.MnSapIf018V2Service;
import com.epoch.app.otsapplicationadaptersdk.sapv2.mnsapif019v2.service.MnSapIf019V2Service;
import com.google.common.collect.Lists;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.List;
import java.util.Objects;

/**
 * @description:
 * @author: yuhw
 * @date: 2022年05月18日 11:30
 **/
@Component
@Primary
public class SapRetryWriteServiceImpl implements SapRetryWriteService {
    private Log log = Log.getLogger(SapRetryWriteServiceImpl.class);
    @Resource
    private SapRetryService sapRetryService;
    @Resource(type = MnSapIf008ServiceImpl.class)
    private MnSapIf008Service mnSapIf008Service;
    @Resource(type = MnSapIf013ServiceImpl.class)
    private MnSapIf013Service mnSapIf013Service;
    @Resource(type = MnSapIf007ServiceImpl.class)
    private MnSapIf007Service mnSapIf007Service;
    @Resource(type = MnSapIf018ServiceImpl.class)
    private MnSapIf018Service mnSapIf018Service;
    @Resource(type = MnSapIf017ServiceImpl.class)
    private MnSapIf017Service mnSapIf017Service;
    @Resource(type = MnSapIf015ServiceImpl.class)
    private MnSapIf015Service mnSapIf015Service;


    @Resource(type = MnSapIf008V2ServiceImpl.class)
    private MnSapIf008V2Service mnSapIf008V2Service;
    @Resource(type = MnSapIf013V2ServiceImpl.class)
    private MnSapIf013V2Service mnSapIf013V2Service;
    @Resource(type = MnSapIf007V2ServiceImpl.class)
    private MnSapIf007V2Service mnSapIf007V2Service;
    @Resource(type = MnSapIf018V2ServiceImpl.class)
    private MnSapIf018V2Service mnSapIf018V2Service;
    @Resource(type = MnSapIf017V2ServiceImpl.class)
    private MnSapIf017V2Service mnSapIf017V2Service;
    @Resource(type = MnSapIf015V2ServiceImpl.class)
    private MnSapIf015V2Service mnSapIf015V2Service;
    @Resource(type = MnSapIf019V2ServiceImpl.class)
    private MnSapIf019V2Service mnSapIf019V2Service;

//    SAP007("调拨预报单007接口", "MnSapIf007$externalSyncUpdateForecast"),
//    SAP008("调拨单008接口", "MnSapIf008$externalSyncAllocate"),
//    SAP013("调拨单013接口", "MnSapIf013$externalUpdateAllocateBySaleOrder"),
//    SAP018("交货单删除018接口", "MnSapIf018$externalSyncDeliveryOrder"),
//    SAP017("交货单同步017接口", "MnSapIf017$externalSyncDeliveryOrder"),
//    SAP015("销售单同步015接口", "MnSapIf015$externalSyncSaleOrder"),
//    SAP016("发票同步016接口", "MnSapIf016$externalSyncInvoice");

    private static final String SAP007V2 = "MnSapIf007V2$externalSyncUpdateForecast";
    private static final String SAP008V2 = "MnSapIf008V2$externalSyncAllocate";
    private static final String SAP013V2 = "MnSapIf013V2$externalUpdateAllocateBySaleOrder";
    private static final String SAP018V2 = "MnSapIf018V2$externalSyncDeliveryOrder";
    private static final String SAP017V2 = "MnSapIf017V2$externalSyncDeliveryOrder";
    private static final String SAP015V2 = "MnSapIf015V2$externalSyncSaleOrder";
    private static final String SAP019V2 = "MnSapIf019V2$externalSyncSaleOrderDelete";
//    private static final String SAP016V2 = "MnSapIf007V2$externalSyncUpdateForecast";

    private static final Integer MAX_PAGE_SIZE = 1000;
    //最大重试次数
    private static final int MAX_RETRY_TIMES = 80;
    //能否重试 默认重试
    @Value("${ots.canRetry:1}")
    private boolean canRetry;

    @Override
    public Result<SapRetrySaveResponse> save(SapRetrySaveRequest sapRetrySaveRequest) {
        SapRetrySaveResponse response = new SapRetrySaveResponse();
        try {
            SapRetryLoadListRequest sapRetryLoadListRequest = new SapRetryLoadListRequest();
            sapRetryLoadListRequest.setMessageId(sapRetrySaveRequest.getMessageId());
            Result<List<SapRetry>> listResult = sapRetryService.loadList(sapRetryLoadListRequest);
            //查不到创建
            if (listResult == null || CollectionUtils.isEmpty(listResult.getResult())) {
                SapRetry sapRetry = new SapRetry();
                sapRetry.setRetryTimes(0);
                sapRetry.setRequestTime(sapRetrySaveRequest.getRequestTime());
                sapRetry.setMessageId(sapRetrySaveRequest.getMessageId());
                sapRetry.setOutKey(sapRetrySaveRequest.getOutKey());
                sapRetry.setApiCode(sapRetrySaveRequest.getApiCode());
                sapRetry.setPriority(0);
                sapRetry.setParam(sapRetrySaveRequest.getParam());
                sapRetry.setStatus(RetryStatus.FAIL.getValue());
                sapRetry.setMsg(sapRetrySaveRequest.getMsg());
                sapRetry.setExt(sapRetrySaveRequest.getExt());
                sapRetryService.create(sapRetry);
                response.setSucces(true);
                return Result.success(response);
            }
            //更新sap接口重试记录
            SapRetry sapRetry = listResult.getResult().get(0);
            sapRetry.setRetryTimes(sapRetry.getRetryTimes() + 1);
            sapRetry.setMsg(sapRetrySaveRequest.getMsg());
            sapRetry.setParam(sapRetrySaveRequest.getParam());
            sapRetry.setRequestTime(sapRetrySaveRequest.getRequestTime());
             sapRetryService.update(sapRetry);
            response.setSucces(true);
        }catch (Throwable e){
            response.setSucces(false);
            response.setMsg(e.getMessage());
            log.error("sapRetryService_save_error:{},request:{}",e.getMessage(), JSON.toJSONString(sapRetrySaveRequest));
        }
        return Result.success(response);
    }

    /**
     * sap接口重试
     * @param sapRetryRetryRequest
     * @return
     */
    @Override
    public SapRetryRetryResponse retry(SapRetryRetryRequest sapRetryRetryRequest) {
        SapRetryRetryResponse response = new SapRetryRetryResponse();
        response.setSuccess(false);
        if (sapRetryRetryRequest == null || sapRetryRetryRequest.getId() == null){
            response.setMsg("参数校验为空");
            return response;
        }
//        SapRetryLoadListRequest sapRetryLoadListRequest = new SapRetryLoadListRequest();
//        sapRetryLoadListRequest.setId(sapRetryRetryRequest.getId());
//        sapRetryService.loadList()
        LoadRequest request = new LoadRequest();
        request.setId(sapRetryRetryRequest.getId());
        SapRetry sapRetry = sapRetryService.load(request);
        if (sapRetry == null){
            response.setMsg("重试记录查询为空");
            return response;
        }


        MnSapCommResponse mnSapCommResponse;
        try {
            if (SapApiCode.SAP008.getValue().equalsIgnoreCase(sapRetry.getApiCode()) || SAP008V2.equalsIgnoreCase(sapRetry.getApiCode())){
                MnSapIf008Request mnSapIf008Request = JSON.parseObject(sapRetry.getParam(),MnSapIf008Request.class);
//                mnSapCommResponse = mnSapIf008Service.externalSyncAllocate(mnSapIf008Request);
                mnSapCommResponse = mnSapIf008V2Service.externalSyncAllocate(mnSapIf008Request);
            }else if (SapApiCode.SAP013.getValue().equalsIgnoreCase(sapRetry.getApiCode()) || SAP013V2.equalsIgnoreCase(sapRetry.getApiCode())){
                MnSapIf013Request mnSapIf013Request = JSON.parseObject(sapRetry.getParam(),MnSapIf013Request.class);
//                mnSapCommResponse = mnSapIf013Service.externalUpdateAllocateBySaleOrder(mnSapIf013Request);
                mnSapCommResponse = mnSapIf013V2Service.externalUpdateAllocateBySaleOrder(mnSapIf013Request);
            }else if (SapApiCode.SAP007.getValue().equalsIgnoreCase(sapRetry.getApiCode()) || SAP007V2.equalsIgnoreCase(sapRetry.getApiCode())){
                MnSapIf007Request mnSapIf007Request = JSON.parseObject(sapRetry.getParam(),MnSapIf007Request.class);
//                mnSapCommResponse = mnSapIf007Service.externalSyncUpdateForecast(mnSapIf007Request);
                mnSapCommResponse = mnSapIf007V2Service.externalSyncUpdateForecast(mnSapIf007Request);
            }else if (SapApiCode.SAP018.getValue().equalsIgnoreCase(sapRetry.getApiCode()) || SAP018V2.equalsIgnoreCase(sapRetry.getApiCode())){
                MnSapIf018Request mnSapIf018Request = JSON.parseObject(sapRetry.getParam(),MnSapIf018Request.class);
                mnSapCommResponse = mnSapIf018V2Service.externalSyncDeliveryOrder(mnSapIf018Request);
            }else if (SapApiCode.SAP017.getValue().equalsIgnoreCase(sapRetry.getApiCode()) || SAP017V2.equalsIgnoreCase(sapRetry.getApiCode())){
                MnSapIf017Request mnSapIf017Request = JSON.parseObject(sapRetry.getParam(),MnSapIf017Request.class);
                mnSapCommResponse = mnSapIf017V2Service.externalSyncDeliveryOrder(mnSapIf017Request);
            }else if (SapApiCode.SAP015.getValue().equals(sapRetry.getApiCode()) || SAP015V2.equalsIgnoreCase(sapRetry.getApiCode())){
                MnSapIf015Request mnSapIf015Request = JSON.parseObject(sapRetry.getParam(),MnSapIf015Request.class);
                mnSapCommResponse = mnSapIf015V2Service.externalSyncSaleOrder(mnSapIf015Request);
            }else if (SapApiCode.SAP019.getValue().equals(sapRetry.getApiCode())){
                MnSapIf019Request mnSapIf019Request = JSON.parseObject(sapRetry.getParam(), MnSapIf019Request.class);
                mnSapCommResponse = mnSapIf019V2Service.externalSyncSaleOrderDelete(mnSapIf019Request);
            }else  {
                log.error("sapRetry_ApiCode_Not_Match:{}",JSON.toJSONString(sapRetry));
                return response;
            }
            response = convert(mnSapCommResponse);
        }catch (Throwable e){
            log.error("sapRetry_error:{}",sapRetry.getParam());
            log.error("sapRetry_error",e);

        }
        return response;
    }

    /**
     * 批量重试
     * @param sapRetryBatchRetryRequest
     * @return
     */
    @Override
    public Result<SapRetryBatchRetryResponse> batchRetry(SapRetryBatchRetryRequest sapRetryBatchRetryRequest) {
        SapRetryBatchRetryResponse sapRetryBatchRetryResponse = new SapRetryBatchRetryResponse();
        List<Long> successIds = Lists.newArrayList();
        //获取失败的1000条
        SapRetryLoadListRequest sapRetryLoadListRequest = new SapRetryLoadListRequest();
        sapRetryLoadListRequest.setRetryTimes(MAX_RETRY_TIMES);
        //2022.09.02 添加apiCode执行特定的接口
        if (sapRetryBatchRetryRequest != null && StringUtils.isNotBlank(sapRetryBatchRetryRequest.getApiCode())){
            sapRetryLoadListRequest.setApiCode(sapRetryBatchRetryRequest.getApiCode());
        }
        Result<Integer> failListCount = sapRetryService.getFailListCount(sapRetryLoadListRequest);
        log.info("SapRetryWriteServiceImpl_getFailListCount:{}",JSON.toJSONString(failListCount));
        //查询条数为空直接返回
//        if (failListCount == null || failListCount.getResult() == null || failListCount.getResult().getTotal() == null){
//            return Result.success(sapRetryBatchRetryResponse);
//        }
//        Integer total = failListCount.getResult().getTotal();
        if (failListCount == null || failListCount.getResult() == null){
            return Result.success(sapRetryBatchRetryResponse);
        }
        Integer total = failListCount.getResult();
        List<List<SapRetry>> listList = Lists.newArrayList();
        if (total > MAX_PAGE_SIZE){
            Integer totalPage = total % MAX_PAGE_SIZE ==0 ? total/MAX_PAGE_SIZE : total/MAX_PAGE_SIZE +1;
            //分页循环查询
            for (Integer i = 0; i < totalPage; i++) {
                sapRetryLoadListRequest.setStart(i * MAX_PAGE_SIZE);
                sapRetryLoadListRequest.setLimit(MAX_PAGE_SIZE);
                sapRetryLoadListRequest.setRetryTimes(MAX_RETRY_TIMES);
                Result<List<SapRetry>> listResult = sapRetryService.getFailList(sapRetryLoadListRequest);
                if (listResult != null && CollectionUtils.isNotEmpty(listResult.getResult())){
                    listList.add(listResult.getResult());
                }
            }
        }else {
            sapRetryLoadListRequest.setRetryTimes(MAX_RETRY_TIMES);
            sapRetryLoadListRequest.setLimit(MAX_PAGE_SIZE);
            sapRetryLoadListRequest.setStart(0);
            Result<List<SapRetry>> listResult = sapRetryService.getFailList(sapRetryLoadListRequest);
            if (listResult != null && CollectionUtils.isNotEmpty(listResult.getResult())){
                listList.add(listResult.getResult());
            }
        }
        if (CollectionUtils.isEmpty(listList)){
            log.info("SapRetryWriteServiceImpl_batchRetry_empty");
            return Result.success(sapRetryBatchRetryResponse);
        }
        for (List<SapRetry> sapRetryList : listList) {
            for (SapRetry sapRetry : sapRetryList) {
                try {
                    SapRetryRetryRequest sapRetryRetryRequest = new SapRetryRetryRequest();
                    sapRetryRetryRequest.setId(sapRetry.getId());
                    SapRetryRetryResponse sapRetryRetryResponse = retry(sapRetryRetryRequest);
                    sapRetry.setRetryTimes(sapRetry.getRetryTimes() + 1);
                    if (Objects.equals(Boolean.TRUE,sapRetryRetryResponse.getSuccess())){
                        sapRetry.setStatus(RetryStatus.SUCCESS.getValue());
                        successIds.add(sapRetry.getId());
                    }else {
                        LoadRequest loadRequest = new LoadRequest();
                        loadRequest.setId(sapRetry.getId());
                        SapRetry load = sapRetryService.load(loadRequest);
                        if (load == null || RetryStatus.SUCCESS.getValue().equals(load.getStatus())){
                            log.info("SapRetryWriteServiceImpl_retry_isSucceed:{}",JSON.toJSONString(load));
                            continue;
                        }
                        sapRetry.setStatus(RetryStatus.FAIL.getValue());
                        if (StringUtils.isNotBlank(sapRetryRetryResponse.getMsg())){
                            sapRetry.setMsg(sapRetryRetryResponse.getMsg());
                        }
                    }
                    sapRetryService.update(sapRetry);
                }catch (Throwable e){
                    log.error("sapBathRetry_error:{}",JSON.toJSONString(sapRetry));
                    log.error("sapBathRetry_error",e);
                    continue;
                }
            }
        }

//        sapRetryLoadListRequest.setRetryTimes(MAX_RETRY_TIMES);
//        sapRetryLoadListRequest.setStart(0);
//        sapRetryLoadListRequest.setLimit(MAX_PAGE_SIZE);
//        //理论上原来的load也能改造使用. 暂时用这种吧
//        Result<List<SapRetry>> listResult = sapRetryService.getFailList(sapRetryLoadListRequest);
//        Result<List<SapRetry>> listResult = sapRetryService.loadList(sapRetryLoadListRequest);
//        if (Objects.nonNull(listResult) && CollectionUtils.isNotEmpty(listResult.getResult()) && canRetry){
//            for (SapRetry sapRetry : listResult.getResult()) {
//                try {
//                    SapRetryRetryRequest sapRetryRetryRequest = new SapRetryRetryRequest();
//                    sapRetryRetryRequest.setId(sapRetry.getId());
//                    SapRetryRetryResponse sapRetryRetryResponse = retry(sapRetryRetryRequest);
//                    sapRetry.setRetryTimes(sapRetry.getRetryTimes() + 1);
//                    if (Objects.equals(Boolean.TRUE,sapRetryRetryResponse.getSuccess())){
//                        sapRetry.setStatus(RetryStatus.SUCCESS.getValue());
//                        successIds.add(sapRetry.getId());
//                    }else {
//                        sapRetry.setStatus(RetryStatus.FAIL.getValue());
//                        if (StringUtils.isNotBlank(sapRetryRetryResponse.getMsg())){
//                            sapRetry.setMsg(sapRetryRetryResponse.getMsg());
//                        }
//                    }
//                    sapRetryService.update(sapRetry);
//                }catch (Throwable e){
//                    log.error("sapBathRetry_error:{}",JSON.toJSONString(sapRetry));
//                    log.error("sapBathRetry_error",e);
//                    continue;
//                }
//            }
//        }
        sapRetryBatchRetryResponse.setIds(successIds);
        return Result.success(sapRetryBatchRetryResponse);
    }

    SapRetryRetryResponse convert(MnSapCommResponse mnSapCommResponse){
        SapRetryRetryResponse response = new SapRetryRetryResponse();
        response.setSuccess(false);
        if (Objects.nonNull(mnSapCommResponse) && CollectionUtils.isNotEmpty(mnSapCommResponse.getData())
            && Objects.nonNull(mnSapCommResponse.getData().get(0).getStatus())){
            if (mnSapCommResponse.getData().get(0).getStatus().equalsIgnoreCase("S")){
                response.setSuccess(true);
            }else {
                String message = mnSapCommResponse.getData().get(0).getMessage();
                if (StringUtils.isNotBlank(message)){
                    response.setMsg(message);
                }
            }
        }
        return response;
    }
}
